﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;

namespace AudioCore.Common
{
    public class AnyConfig : System.Configuration.AppSettingsReader
    {
        private XmlNode node;
        public string ConfigFile { get; set; }

        public string GetValue(string key)
        {
            return Convert.ToString(GetValue(key, typeof(string)));
        }

        public new object GetValue(string key, System.Type sType)
        {
            XmlDocument doc = new XmlDocument();
            object ro = String.Empty;
            LoadDoc(doc);
            string sNode = key.Substring(0, key.LastIndexOf("//"));
            // retrieve the selected node

            try
            {
                node = doc.SelectSingleNode(sNode);
                if (node != null)
                {
                    // Xpath selects element that contains the key

                    XmlElement targetElem = (XmlElement)node.SelectSingleNode(
                       key.Replace(sNode, ""));
                    if (targetElem != null)
                    {
                        ro = targetElem.GetAttribute("value");
                    }
                }
                if (sType == typeof(string))
                    return Convert.ToString(ro);
                else
                    if (sType == typeof(bool))
                    {
                        if (ro.Equals("True") || ro.Equals("False"))
                            return Convert.ToBoolean(ro);
                        else
                            return false;
                    }
                    else
                        if (sType == typeof(int))
                            return Convert.ToInt32(ro);
                        else
                            if (sType == typeof(double))
                                return Convert.ToDouble(ro);
                            else
                                if (sType == typeof(DateTime))
                                    return Convert.ToDateTime(ro);
                                else
                                    return Convert.ToString(ro);
            }
            catch
            {
                return String.Empty;
            }
        }

        public bool SetValue(string key, string val)
        {
            XmlDocument doc = new XmlDocument();
            LoadDoc(doc);
            try
            {
                // retrieve the target node

                string sNode = key.Substring(0, key.LastIndexOf("//"));
                node = doc.SelectSingleNode(sNode);
                if (node == null)
                    return false;
                // Set element that contains the key

                XmlElement targetElem = (XmlElement)node.SelectSingleNode(
                     key.Replace(sNode, ""));
                if (targetElem != null)
                {
                    // set new value

                    targetElem.SetAttribute("value", val);
                }
                // create new element with key/value pair and add it

                else
                {
                    // handle xxx[@key='yyy']

                    sNode = key.Substring(key.LastIndexOf("//") + 2);
                    // create new element xxx

                    XmlElement entry = doc.CreateElement(sNode.Substring(0,
                       sNode.IndexOf("[@")).Trim());
                    sNode = sNode.Substring(sNode.IndexOf("'") + 1);
                    // set attribute key=yyy

                    entry.SetAttribute("key", sNode.Substring(0,
                         sNode.IndexOf("'")));
                    // set attribute value=val

                    entry.SetAttribute("value", val);
                    node.AppendChild(entry);
                }
                SaveDoc(doc, this.ConfigFile);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool RemoveElement(string key)
        {
            XmlDocument doc = new XmlDocument();
            LoadDoc(doc);
            try
            {
                string sNode = key.Substring(0, key.LastIndexOf("//"));
                // retrieve the appSettings node

                node = doc.SelectSingleNode("//appSettings");
                if (node == null)
                    return false;
                // XPath select setting element that contains the key to remove

                node.RemoveChild(node.SelectSingleNode(key.Replace(sNode, "")));
                SaveDoc(doc, this.ConfigFile);
                return true;
            }
            catch
            {
                return false;
            }
        }

        private void SaveDoc(XmlDocument doc, string docPath)
        {
            // save document

            // choose to ignore if web.config since it may 

            // cause server sessions interruptions

            if (this.ConfigFile.Equals("web.config"))
                return;
            else
                try
                {
                    XmlTextWriter writer = new XmlTextWriter(docPath, null);
                    writer.Formatting = Formatting.Indented;
                    doc.WriteTo(writer);
                    writer.Flush();
                    writer.Close();
                    return;
                }
                catch
                { }
        }

        private void LoadDoc(XmlDocument doc)
        {
            // check for type of config file being requested

            if (this.ConfigFile.Equals("app.config"))
            {
                // use default app.config

                this.ConfigFile = ((Assembly.GetEntryAssembly()).GetName()).Name +
                   ".exe.config";
            }
            else
                if (this.ConfigFile.Equals("web.config"))
                {
                    // use server web.config

                    this.ConfigFile = System.Web.HttpContext.Current.Server.MapPath(
                      "web.config");
                }
            // load the document

            doc.Load(this.ConfigFile);
        }

    }
}
